﻿using System;
using System.Linq;
using System.Text;
using DevExpress.Xpo;
using DevExpress.ExpressApp;
using System.ComponentModel;
using DevExpress.ExpressApp.DC;
using DevExpress.Data.Filtering;
using DevExpress.Persistent.Base;
using System.Collections.Generic;
using DevExpress.ExpressApp.Model;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Persistent.Validation;

namespace aztall.Module.BusinessObjects
{
	[ImageName("BO_Sale_V92")]
	public class PromoCost : DomainObject
	{
		protected Customer _Customer;
		protected Sku _Sku;
		protected double _Rate = 0;
		protected string _Description;
		protected Metric _Metric;

		[Persistent("PromoLineCost")]
		protected double? _PromoLineCost;


		public PromoCost(Session session)
				: base(session)
		{
		}
		public override void AfterConstruction()
		{
			base.AfterConstruction();
		}
		protected override void OnLoaded()
		{
			_PromoLineCost = null;
			base.OnLoaded();
		}
		private Promo _Promo;
		[Association("Promo_PromoCosts", UseAssociationNameAsIntermediateTableName = true), XafDisplayName("Promotion")]
		public Promo Promo
		{
			get { return _Promo; }
			set
			{
				Promo _oldPromo = _Promo;
				SetPropertyValue(nameof(Promo), ref _Promo, value);
				if (!IsLoading && !IsSaving && _oldPromo != _Promo)
				{
					_oldPromo = _oldPromo ?? _Promo;
					_oldPromo.UpdatePromoCosts(true, this);
				}
			}
		}
		#region properties
		[DataSourceCriteria("MetricType ='" + MetricType.PromoCost + "'")]
		[RuleRequiredField(DefaultContexts.Save, SkipNullOrEmptyValues = false), ImmediatePostData]
		public Metric Metric
		{
			get { return _Metric; }
			set
			{
				Metric _oldValue = _Metric;
				SetPropertyValue(nameof(Metric), ref _Metric, value);

				if (String.IsNullOrWhiteSpace(_Description) || (_Description == (_oldValue == null ? string.Empty : _oldValue.MetricDesc)))
					Description = (_Metric == null ? string.Empty : _Metric.MetricDesc);

				if (!IsLoading && !IsSaving && Promo != null)
					Promo.UpdatePromoCosts(true, this);


			}
		}
		[Index(2)]
		public string Description
		{
			get { return _Description; }
			set { SetPropertyValue<string>("Description", ref _Description, value); }
		}
		[DataSourceProperty("Promo.Customers"), ImmediatePostData]
		[Index(3)]
		public Customer Customer
		{
			get { return _Customer; }
			set
			{
				SetPropertyValue(nameof(Customer), ref _Customer, value);
				if (!IsLoading && !IsSaving && Promo != null)
					Promo.UpdatePromoCosts(true, this);
			}
		}
		[DataSourceProperty("Promo.Skus"), ImmediatePostData]
		[Index(4)]
		public Sku Sku
		{
			get { return _Sku; }
			set
			{
				SetPropertyValue(nameof(Sku), ref _Sku, value);
				if (!IsLoading && !IsSaving && Promo != null)
					Promo.UpdatePromoCosts(true, this);
			}
		}
		[RuleRequiredField(DefaultContexts.Save, SkipNullOrEmptyValues = false), ImmediatePostData]
		[RuleRange("Rate >= 0", DefaultContexts.Save, 0, int.MaxValue, ResultType = ValidationResultType.Warning, CustomMessageTemplate = "Rate should be a positive number.")]
		[Index(5)]
		public double Rate
		{
			get
			{
				if (
							(Customer == null && _Metric != null && _Metric.MetricCode == CostMetricCode.PerCustomer) ||
							(Sku == null && _Metric != null && _Metric.MetricCode == CostMetricCode.PerSku)
					)
					_Rate = 0.0d;

				return _Rate;
			}
			set
			{
				SetPropertyValue<double>(nameof(Rate), ref _Rate, value);
				if (!IsLoading && !IsSaving && Promo != null)
				{
					Promo.UpdatePromoCosts(true, this);
				}
			}
		}
		#endregion
		[Index(6), XafDisplayName("Line Total"), PersistentAlias("_PromoLineCost")]
		public double? PromoLineCost
		{
			get
			{
				if (_PromoLineCost == null)
					UpdateLineCost(true);
				return _PromoLineCost;
			}
		}
		public double? UpdateLineCostDelta(bool forceChangeEvent, IList<CustomerSkuDW> DWs = null)
		{
			double? oldValue = _PromoLineCost;
			if (Metric != null)
				//PromoLineCost = Promo.CalcLineCost(Metric, Rate, Customer, Sku, oldValue);
				_PromoLineCost = UpdateLineCost(forceChangeEvent);
			else
				_PromoLineCost = 0.0;
			if (forceChangeEvent)
				OnChanged(nameof(PromoLineCost));
			return _PromoLineCost - oldValue;
		}
		public double? UpdateLineCost(bool forceChangeEvent)
		{
			double? oldValue = _PromoLineCost;
			if (Metric != null)
				//PromoLineCost = Promo.CalcLineCost(Metric, Rate, Customer, Sku, oldValue);
				_PromoLineCost = Metric.TotalValue(Promo, Customer, Sku, Rate);
			else
				_PromoLineCost = 0.0;
			if (forceChangeEvent)
				OnChanged(nameof(PromoLineCost));
			return _PromoLineCost;
		}
	}
}
